#include <signal.h>
#include <iostream>
#include <unistd.h>
#include <vector>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <string>
#include <cstdlib>
#include <functional>
using namespace std;

typedef function<void()> func;
vector<func> callbacks;
uint64_t count = 0;
void showCount()
{
    // cout << "进程捕捉到一个信号，正在处理中： " << signum << " | Pid: " << getpid() << endl;
    cout << "finanl socre :" << count << endl;
}
void showLog()
{
    cout << "这个是日志功能" << endl;
}
void logUser()
{
    if (fork() == 0)
    {
        execl("/usr/bin/who", "who", nullptr);
        exit(1);
    }
    // 父进程等待
    wait(nullptr);
}
// sig
void _catchSig(int signum)
{

    for (auto &f : callbacks)
    {
        f();
    }
    alarm(1);
}
void catchTest(int signum)
{
    cout << "测试回调函数的知识"
         << "信号是：" << signum << endl;
}
void CatchSig()
{
    // 注册信号,第一个参数是信号可以写对应的宏英文名，第二个参数是方法，方法名不带括号,这样的写法是回调函数的参数
    signal(SIGINT, _catchSig); // signal(2,fun);//第一个参数可以写对应的信号编号数字
    while (true)
    {
        cout << "我是一个进程，我在正在运行...,Pid: " << getpid() << endl;
        sleep(1);
    }
    pid_t id = fork();
    if (id == 0)
    {
        int a = 100;
        // a /= 0;
        exit(0);
    }
    int status = 0;
}
static void Usage(string proc)
{
    cout << "Usage:\r\n\t" << proc << " signmuber procID" << endl;
}
// kill接口发送信号的方式
void Sign_kill(int argc, char *argv[])
{
    if (argc != 3)
    {
        Usage(argv[0]);
        exit(1);
    }
    int signumber = atoi(argv[1]); // 字符型信号转化为整型
    int procid = atoi(argv[2]);    // 字符型进程id转化为整型
    // 系统调用
    kill(procid, signumber); // kill不仅是终止进程，也能发送信号
}
void SignMyshell()
{
    cout << "我开始运行了" << endl;
    sleep(1);
    raise(8); // 自己给自己发送8号信号
    signal(2, SIG_DFL);
}

void MyAlarm()
{
    alarm(1); // 设定1秒,1秒过完向进程发送闹钟信号
    // 单纯计算算力
    signal(SIGALRM, _catchSig);
    callbacks.push_back(showCount);
    callbacks.push_back(showLog);
    callbacks.push_back(logUser);

    while (true)
        count++;
}
// 命令行参数./mykill -2 pid
int main(int argc, char *argv[])
{
    return 0;
}